/**
 * \file Singleton.h
 * \brief Singleton definition and declaration class
 * \author Edouard ROGE
 * \date 08 august 2012
 */

#ifndef _SINGLETON_
#define _SINGLETON_

#ifdef CORE_LINUX_EXPORTS
#define CORE_LINUX __attribute__((visibility("default")))
#else 
#define CORE_LINUX 
#endif

#include <stdlib.h>
#include <iostream>

namespace Core
{
	/**
	 * \class Singleton
	 * \brief Base class to create a singleton.
	 */
	template<typename T>
	class CORE_LINUX Singleton
	{
	public:

		/**
		 * \fn static T & GetInstance()
		 * \brief get the singleton
		 * \return instance of the singleton
		 */
		static T & GetInstance()
		{
			if (ms_pInstance == NULL)
			{
				ms_pInstance = new T();
			}
			return *ms_pInstance;
		}

		/**
		* \fn static T * GetPointerInstance()
		* \brief get the pointer of the singleton
		* \return Pointer on the instance of the singleton
		*/
		static T * GetPointerInstance()
		{
			if (ms_pInstance == NULL)
			{
				ms_pInstance = new T();
			}
			return ms_pInstance;
		}

		/**
		 * \fn static void SetInstance(T * _pInstance)
		 * \brief Set new value for the singleton
		 * \param _pInstance New instance of the singleton
		 */
		static void SetInstance(T * _pInstance)
		{
			DeleteInstance();
			ms_pInstance = _pInstance;
		}

		/**
		 * \fn static void DeleteInstance()
		 * \brief Delete the singleton
		 */
		static void DeleteInstance()
		{
			if (ms_pInstance != NULL)
			{
				delete ms_pInstance;
			}
		}

	protected:

		/**
		 * \fn Singleton();
		 * \brief Constructor
		 */
		Singleton();

		/** Instance of the singleton */
		static T * ms_pInstance;
	};

	template<class T>
	Singleton<T>::Singleton()
	{
	}

	template<class T> T * Singleton<T>::ms_pInstance = NULL;
}
#endif // _SINGLETON_
